# -*- coding: utf-8 -*-

from datetime import date

from django.db import models

from django.conf import settings

from django.core.validators import RegexValidator

from django.contrib.auth.models import User

from django.db import transaction

from core.utils import check_emso, birth_date_matcher, get_group

from exams.models import SubjectYear, SubjectParticipant

def make_enrollment_number_prefix():
  # Faculty number
  prefix = '63'

  # Year's  last two digits
  prefix += str(date.today().year)[-2:]

  # Prefix created
  return prefix

def get_old_enrollment_sheet(emso):
  older_enrollment_sheet = EnrollmentSheet.objects.filter(emso = emso)
  if birth_date_matcher.match(emso) is None and older_enrollment_sheet.exists():
    return older_enrollment_sheet[0].student.latest_enrollment_sheet

  return None

class EnrollmentSheet(models.Model):
  student = models.ForeignKey('Student', null = True, editable = False, db_index = True, related_name = 'enrollment_sheets')
  first_name = models.CharField(max_length = 200, validators = [RegexValidator(ur'^[a-žA-Ž]*$', u'Polje je lahko samo iz črk')], verbose_name='Ime')
  last_name = models.CharField(max_length = 200, validators = [RegexValidator(ur'^[a-žA-Ž]*$', u'Polje je lahko samo iz črk')], verbose_name='Priimek')
  maiden_name = models.CharField(max_length = 200, validators = [RegexValidator(ur'^[a-žA-Ž]*$', u'Polje je lahko samo iz črk')], blank = True, verbose_name= 'Dekliški priimek')
  image = models.ImageField(upload_to = 'img/students/%Y/', blank = True, verbose_name='Slika')
  emso = models.CharField(max_length = 13, validators = [check_emso], verbose_name='EMŠO')
  vat_number = models.CharField(max_length = 8, validators = [RegexValidator(r'\d{8}', u'Davčna številka je sestavljena iz natančno 8 števk')], verbose_name='Davčna številka')
  special_needs = models.CharField(max_length = 1, blank = True, choices = settings.SPECIAL_NEEDS, verbose_name='Študent s posebnimi potrebami')
  email = models.EmailField(blank = True, verbose_name = u'E-poštni naslov')
  telephone = models.CharField(max_length = 15, blank = True, verbose_name = u'Telefonska številka')
  permanent_street = models.CharField(max_length = 200, verbose_name='Ulica in hišna številka')
  permanent_postal_number = models.ForeignKey('core.Post', related_name = 'permanent_enrollment_sheet_set', verbose_name='Pošta', limit_choices_to = {'inactive': False})
  permanent_commune = models.ForeignKey('core.Commune', related_name = 'permanent_enrollment_sheet_set', verbose_name='Občina', limit_choices_to = {'inactive': False})
  country = models.ForeignKey('core.Country', verbose_name = 'Država', limit_choices_to = {'inactive': False})
  temporary_street = models.CharField(max_length = 200, blank = True, verbose_name='Začasna ulica in hišna številka')
  temporary_postal_number = models.ForeignKey('core.Post', null = True, blank = True, related_name = 'temporary_enrollment_sheet_set', verbose_name='Začasna pošta', limit_choices_to = {'inactive': False})
  temporary_commune = models.ForeignKey('core.Commune', null = True, blank = True, related_name = 'temporary_enrollment_sheet_set', verbose_name='Začasna občina', limit_choices_to = {'inactive': False})
  institution = models.CharField(max_length = 3, choices = settings.INSTITUTIONS, verbose_name='Visokošolski zavod')
  student_program = models.ForeignKey('core.Program', verbose_name='Študijski program', limit_choices_to = {'inactive': False})
  student_course_group = models.ForeignKey('core.CourseGroup', blank = True, null = True, verbose_name='Smer in izbirna skupina', help_text = u'Pri bolonjskem programu pustite prazno', limit_choices_to = {'inactive': False})
  student_group = models.CharField(max_length = 2, blank = True, verbose_name = 'Skupina')
  academic_year = models.CharField(max_length = 7, help_text = u'Šolsko leto v obliki YYYY/YY', validators = [RegexValidator(r'\d{4}/\d{2}', u'Napačna oblika')], verbose_name='Študijsko leto')
  study_type = models.CharField(max_length = 1, choices = settings.STUDY_TYPES, verbose_name='Vrsta študija')
  student_year = models.CharField(max_length = 1, choices = settings.STUDENT_YEARS, verbose_name='Letnik študija')
  full_time_student = models.BooleanField(verbose_name=u'Redni študij')
  distance_education = models.BooleanField(verbose_name='Študij na daljavo')
  enrollment_type = models.CharField(max_length = 2, choices = settings.ENROLLMENT_TYPES, verbose_name='Vrsta vpisa')
  studying_location = models.ForeignKey('core.Commune', null = True, blank = True, verbose_name='Kraj izvajanja študija', help_text = u'Izpolni se samo, če študira izven matične ustanove', limit_choices_to = {'inactive': False})
  additional_studying_insitution = models.CharField(max_length = 3, choices = settings.INSTITUTIONS, blank = True, verbose_name='Na katerem visokošolskem zavodu še študirate?')
  created = models.DateTimeField(auto_now_add = True, db_index = True)

  class Meta:
    unique_together = (
      ('emso', 'academic_year', 'student', 'student_program', 'student_year', 'student_course_group'),
    )

  @transaction.commit_on_success
  def save(self, *args, **kwargs):
    # Check for enrollment sheet with same emso, only if we have a real emso or we already have a student specified
    if self.student:
      older_enrollment_sheet = self.student.latest_enrollment_sheet
    else:
      older_enrollment_sheet = get_old_enrollment_sheet(self.emso)

    # Make the first save
    super(EnrollmentSheet, self).save(*args, **kwargs)

    if older_enrollment_sheet is None:
      # Create a new student
      enrollment_number = make_enrollment_number_prefix()

      # Generate new enrollment number
      enrollment_number += format(Student.objects.filter(enrollment_number__startswith = enrollment_number).count(), '04d')

      # Let's add this new student into Django system
      user = User.objects.create_user(enrollment_number, '', enrollment_number)
      # Add the student to it's students group
      user.groups.add(get_group('students'))
      user.save()

      # And create the student info table
      student = Student()
      student.enrollment_number = enrollment_number
      student.user = user

      # Connect this enrollment sheet with new student
      self.student = student
      # And not to forget with the profile
      profile = user.get_profile()
      profile.student = student
      profile.save()
    else:
      # No need to create a new student, since we have one...
      self.student = older_enrollment_sheet.student

      # If image is empty, take the previous one
      if self.image is None:
        self.image = older_enrollment_sheet.image

    # Sync Django's student info
    self.student.latest_enrollment_sheet = self
    self.student.save()

    self.student.user.first_name = self.first_name
    self.student.user.last_name = self.last_name
    self.student.user.save()

    # Sync students subject list
    def sync_subjects(enrollment_sheet):
      add_args = {
        'school_year_start': enrollment_sheet.academic_year_start(),
        'school_year_end': enrollment_sheet.academic_year_end(),
        'subject__subjectprogram__obligatory': True,
        'subject__programs': enrollment_sheet.student_program,
        'subject__subjectprogram__course_group': enrollment_sheet.student_course_group,
        'subject__subjectprogram__year__exact': enrollment_sheet.student_year,
        'subject__inactive': False
      }
      search_args = {
        'subject__school_year_start': enrollment_sheet.academic_year_start(),
        'subject__school_year_end': enrollment_sheet.academic_year_end(),
        'subject__subject__subjectprogram__obligatory': True,
        'subject__subject__programs': enrollment_sheet.student_program,
        'subject__subject__subjectprogram__course_group': enrollment_sheet.student_course_group,
        'subject__subject__subjectprogram__year__exact': enrollment_sheet.student_year,
        'student': enrollment_sheet.student
      }

      if SubjectParticipant.objects.filter(**search_args).exists() is False:
        for subject in SubjectYear.objects.filter(**add_args):
          participation = SubjectParticipant(subject = subject, student = enrollment_sheet.student)
          participation.save()

    enlisted_programs = [(self.student_program, self.student_course_group, self.student_year)]
    # Add subject for current enrollment sheet
    sync_subjects(self)
    # Sync other enrollment sheets
    for enrollment_sheet in EnrollmentSheet.objects.filter(academic_year = self.academic_year, student = self.student):
      sync_subjects(enrollment_sheet)
      enlisted_programs.append((enrollment_sheet.student_program, enrollment_sheet.student_course_group, enrollment_sheet.student_year))

    # Remove unconnected subjects
    blocked_participations = SubjectParticipant.objects.filter(student = self.student,
                                      subject__school_year_start = self.academic_year_start(),
                                      subject__school_year_end = self.academic_year_end())
    for (program, course_group, year) in enlisted_programs:
      blocked_participations = blocked_participations.filter(subject__subject__programs = program,
                                                             subject__subject__subjectprogram__course_group = course_group,
                                                             subject__subject__subjectprogram__year__exact = year)
    for participant in SubjectParticipant.objects.filter(student = self.student,
                                      subject__school_year_start = self.academic_year_start(),
                                      subject__school_year_end = self.academic_year_end()):
      if participant not in blocked_participations:
        participant.delete()

    # Commit aditional saves
    super(EnrollmentSheet, self).save(*args, **kwargs)

  def academic_year_start(self):
    p = self.academic_year.split("/")
    return int(p[0])

  def academic_year_end(self):
    p = self.academic_year.split("/")
    return int(p[0][:len(p[1])]+p[1])

  def academic_year_tuple(self):
    return (self.academic_year_start(), self.academic_year_end())

  def get_full_time_student_display(self):
    if self.full_time_student == True:
      return "redni vpis"
    else:
      return "izredni vpis"
      
  @staticmethod
  def get_all_years(add_whatever = True):
    queryset_year = SubjectYear.objects.values('school_year_start', 'school_year_end').distinct().order_by("school_year_end")
    choices_academic_year = []
    if add_whatever:
      choices_academic_year.append(('0','Ne glede'))
    for i in queryset_year:
      choices_academic_year.append(
        (str(i['school_year_start'])+'/'+str(i['school_year_end'])[2:], 
        str(i['school_year_start'])+'/'+str(i['school_year_end']))
      )
    return choices_academic_year

  @staticmethod
  def next_school_year(school_year):   
    s = str(school_year)
    p = s.split("/")
    s = int(s[0:2]+p[1])
    e = s + 1
    return str(s)+"/"+str(e)[2:4]
    
  def __unicode__(self):
    return u'%s-%s' % (self.student.enrollment_number, self.academic_year)

class Student(models.Model):
  enrollment_number = models.CharField(max_length = 8, primary_key = True)
  user = models.OneToOneField(User, related_name = 'student')
  latest_enrollment_sheet = models.ForeignKey(EnrollmentSheet, related_name = '+')
  modules = models.ManyToManyField('core.ProgramModule',through='exams.StudentModule')

  def get_all_programs(self, add_whatever = False):
    elist = EnrollmentSheet.objects.filter(student=self)
    val = {}
    if add_whatever:
      val = {"0":"Ne glede"}
    for e in elist:
      val[unicode(e.student_program.pk)] = unicode(e.student_program.name)
    programs = val.items()
    return programs
  
  
  def __unicode__(self):
    return u'%s %s' % (self.user.first_name, self.user.last_name)

  class Meta:
    permissions = (
      ('can_search', u'Lahko išče'),
      ('can_view_personal', u'Ima vpogled v osebne podatke študenta'),
      ('can_card_index',u'Lahko pregleduje kartotečni list'),
      ('can_subjects_selection',u'Lahko določa izbirne predmete'),
      ('can_exam_result_paper',u'Lahko vnaša ocene izpita iz prijavnice'),
      ('can_transience', u'Ogled analize prehodnosti'),
      ('can_students_school_year', u'Vpisani v letnik, smer/modul'),
    )
